"use client";
import { useRef, useState, useEffect } from "react";
import { useParams } from "next/navigation";
import * as Y from "yjs";
import { Button } from "@heroui/button";
import { EditorView, basicSetup } from "codemirror";
import { markdown } from "@codemirror/lang-markdown";
import { yCollab } from "y-codemirror.next";
import ReactMarkdown from "react-markdown";
import rehypeHighlight from "rehype-highlight";
import "highlight.js/styles/github.css";

import { CustomSocketProvider } from "@/tools/CustomSocketProvider";

export default function CollaborativeEditor() {
  const { docId: roomName } = useParams(); // 获取路由参数中的文档 ID，作为房间号
  const editorRef = useRef<HTMLDivElement>(null); // 该 ref 用于获取编辑器的 DOM 元素
  const viewRef = useRef<EditorView | null>(null); // 该 ref 用于存储 CodeMirror 的 EditorView 实例

  const [markdownText, setMarkdownText] = useState<string>(""); // 用于存储 Markdown 文本

  const providerRef = useRef<CustomSocketProvider | null>(null); // 该 ref 用于存储 CustomSocketProvider 实例

  // websocket 连接地址
  const WEBSOCKET_URL =
    process.env.NEXT_WEBSOCKET_URL || "http://localhost:1234";

  // 该 useEffect 主要就是用于初始化协同编辑器
  useEffect(() => {
    // 先做一个边界判断
    if (!editorRef.current || viewRef.current || typeof roomName !== "string")
      return;

    // 代码来到这里，说明没有问题，可以开始初始化编辑器了
    const initEditor = async () => {
      try {
        const ydoc = new Y.Doc(); // 创建一个新的 Yjs 文档
        const ytext = ydoc.getText("codemirror"); // 创建一个文本类型的共享副本

        const provider = new CustomSocketProvider(
          `${WEBSOCKET_URL}`,
          roomName,
          ydoc,
        );

        providerRef.current = provider; // 将 provider 存入 ref 中

        // 接下来定义一个更新方法
        // 该更新方法用于从 yjs 共享文档中更新 markdown 编辑器的内容
        const updatePreview = () => setMarkdownText(ytext.toString());

        // 监听 ytext 的变化，只要共享文本数据发生了变化，会触发此事件
        // 然后就会更新编辑器显示的内容
        ytext.observe(updatePreview);

        // 创建一个新的 CodeMirror 编辑器实例，并且进行相应的配置
        viewRef.current = new EditorView({
          // extensions 里面是各种扩展配置
          extensions: [
            basicSetup, // 基本设置，包括常用的功能，例如语法高亮、键盘快捷键、代码缩进
            markdown(), // Markdown 语言支持
            yCollab(ytext, provider.awareness), // 连接 Yjs 文档和 CodeMirror 编辑器
            EditorView.lineWrapping, // 自动换行
            EditorView.theme({
              // 设置编辑器的背景颜色和字体颜色
              "&": {
                backgroundColor: "white", // 设置背景颜色为白色
                color: "black", // 设置文本颜色为黑色
              },
              // 设置代码内容区域的样式
              ".cm-content": {
                fontSize: "16px", // 设置字体大小为16px
                padding: "16px", // 设置内容区域的内边距为16px
              },
              // 设置编辑器滚动区域的样式
              ".cm-scroller": {
                overflow: "auto", // 允许滚动，防止内容溢出
              },
            }), // 配置编辑器相关的主题
          ],
          // 设置父元素，将实例化出来的编辑器挂载到 DOM 上
          parent: editorRef.current!,
        });
      } catch {
        alert("初始化编辑器失败，请稍后再试");
      }
    };

    // 调用初始化编辑器的方法
    initEditor();

    return () => {
      // 组件卸载的时候，做一些清理相关的操作
      if (viewRef.current) {
        viewRef.current.destroy(); // 销毁 CodeMirror 实例
        viewRef.current = null; // 清空 ref
      }
      if (providerRef.current) {
        providerRef.current.destory(roomName); // 销毁 CustomSocketProvider 实例
        providerRef.current = null; // 清空 ref
      }
    };
  }, [roomName]);

  return (
    <div>
      <div className="mb-4">
        <Button className="mr-3" color="primary" size="sm">
          保存文档
        </Button>
        <Button color="danger" size="sm">
          添加协作者
        </Button>
      </div>
      <div className="mb-4">
        <span className="text-sm text-gray-500 mb-4">该文档协作者：</span>
        <div className="flex gap-2 items-center mt-2">
          <span className="text-sm text-gray-400">暂无协作者</span>
        </div>
      </div>
      <div className="grid grid-cols-2 gap-6">
        <div className="flex flex-col h-full bg-white border rounded shadow-sm">
          <h2 className="text-lg font-semibold p-4 border-b">编辑区</h2>
          {/* 编辑器 */}
          <div ref={editorRef} className="flex-1 overflow-auto px-4 pb-4" />
        </div>
        <div className="flex flex-col h-full bg-white border rounded shadow-sm">
          <h2 className="text-lg font-semibold p-4 border-b">预览区</h2>
          <div className="prose prose-sm max-w-none flex-1 overflow-auto p-4">
            <ReactMarkdown rehypePlugins={[rehypeHighlight]}>
              {markdownText}
            </ReactMarkdown>
          </div>
        </div>
      </div>
    </div>
  );
}
